home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 April / EnigmA AMIGA RUN 17 (1997)(G.R. Edizioni)(IT)[!][issue 1997-04][EAR-CD].iso / EARCD / text / hyper / hsc_source.lha / hsc / source / ugly / args_prp.c < prev    next >
C/C++ Source or Header  |  1996-11-15  |  13KB  |  448 lines

  1. /*
  2.  * ugly/args_prp.c
  3.  *
  4.  * ugly argument preparation functions
  5.  *
  6.  * Copyright (C) 1994,95,96  Thomas Aglassinger
  7.  *
  8.  * This program is free software; you can redistribute it and/or modify
  9.  * it under the terms of the GNU General Public License as published by
  10.  * the Free Software Foundation; either version 2 of the License, or
  11.  * (at your option) any later version.
  12.  *
  13.  * This program is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  * GNU General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this program; if not, write to the Free Software
  20.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  *
  22.  * updated: 15-Nov-1996
  23.  * created:  3-Jul-1994
  24.  *
  25.  *===================================================================
  26.  * TODO:
  27.  * - free all memory in error case
  28.  *
  29.  */
  30.  
  31. /*
  32.  * includes
  33.  */
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include <stdarg.h>
  37. #include <string.h>
  38. #include <ctype.h>
  39.  
  40. #include "utypes.h"
  41. #include "umemory.h"
  42. #include "ustring.h"
  43. #include "dllist.h"
  44.  
  45. #define NOEXTERN_UGLY_UARGS_H
  46. #include "uargs.h"
  47.  
  48. /*
  49.  * error vars
  50.  */
  51. LONG prep_error_num;            /* error number */
  52. int prep_error_idx;             /* # of template causing error */
  53. size_t prep_error_pos;          /* pos in arg */
  54. BOOL no_preperr, any_preperr;   /* error flags for _prepare_args() */
  55.  
  56. /*
  57.  * error functions for _prepare_arg()
  58.  *
  59.  */
  60. void set_preperr(LONG num, size_t pos)
  61. {
  62.     if (no_preperr)
  63.     {
  64.  
  65.         no_preperr = FALSE;
  66.         any_preperr = TRUE;
  67.         prep_error_num = num;
  68.         prep_error_pos = pos;
  69.  
  70.     }
  71. }
  72.  
  73. void clr_preperr(void)
  74. {
  75.     no_preperr = TRUE;
  76.     any_preperr = FALSE;
  77.     prep_error_num = 0;
  78.     prep_error_pos = 0;
  79. }
  80.  
  81. /*
  82.  * fprintf_arginfo (debugging aid)
  83.  */
  84. void fprintf_arginfo(FILE * stream, APTR data)
  85. {
  86.     struct arginfo *arg = (struct arginfo *) data;
  87.  
  88.     fprintf(stream, "  %-15s %2lx %2lx",
  89.             arg->ai_id, arg->ai_type, arg->ai_flags);
  90.     if (arg->ai_help)
  91.         printf("  \"%s\"", arg->ai_help);
  92.     fprintf(stream, "\n");
  93. }
  94.  
  95. /*
  96.  * prepare_args
  97.  *
  98.  * convert argument definitions to dllist of struct arginfo
  99.  *
  100.  */
  101. struct arglist *prepare_args(STRPTR arglist_name,...)
  102. {
  103.     va_list ap;
  104.     struct dllist *newlist;
  105.     struct arginfo *newarg;
  106.     struct arglist *new_arglist = NULL;
  107.  
  108.     DA(fprintf(stderr, DUA "prepare_args()\n"));
  109.  
  110.     clr_preperr();              /* clear error vars */
  111.  
  112.     /*
  113.      * alloc & init _new_arglist
  114.      */
  115.     new_arglist = (struct arglist *)
  116.         umalloc(sizeof(struct arglist));
  117.  
  118.     if (new_arglist)
  119.     {
  120.  
  121.         new_arglist->al_name = arglist_name;
  122.         new_arglist->al_list = NULL;
  123.         new_arglist->al_multiple = NULL;
  124.         new_arglist->al_nokeywd = NULL;
  125.  
  126.     }
  127.     else
  128.         set_preperr(APE_NO_MEM, 0);
  129.  
  130.     /*
  131.      * TODO: don't go into if(), when new_arglist failed
  132.      */
  133.  
  134.     /*
  135.      * convert template to double linked list
  136.      */
  137.     newlist = init_dllist(del_arginfo);
  138.  
  139.     if (newlist)
  140.     {
  141.  
  142.         STRPTR nxtdef = NULL;   /* next template definition */
  143.  
  144.         va_start(ap, arglist_name);
  145.  
  146.         do
  147.         {
  148.  
  149.             ufreestr(nxtdef);
  150.             nxtdef = va_arg(ap, STRPTR);        /* get next definition */
  151.  
  152.             /* clone nxtdef: this is necessary because on unix-systems, */
  153.             /* you can not let strtok() run on strings received with    */
  154.             /* va_arg() -> bus error                                    */
  155.             nxtdef = strclone(nxtdef);
  156.             prep_error_idx++;
  157.  
  158.             if (nxtdef)
  159.             {
  160.  
  161.                 DA(fprintf(stderr, DUA "  `%s'\n", nxtdef));
  162.  
  163.                 newarg = umalloc(sizeof(struct arginfo));
  164.  
  165.                 if (newarg)
  166.                 {
  167.  
  168.                     STRPTR new_id;
  169.                     STRPTR typestr;
  170.                     STRPTR flagstr = NULL;
  171.                     STRPTR enumstr = NULL;      /* enum string for type 'E' */
  172.                     LONG new_type = 0;
  173.                     LONG new_flags = 0;
  174.                     LONG rnlolim = 0;
  175.                     LONG rnhilim = 0;
  176.  
  177.                     /* init _newarg */
  178.                     newarg->ai_id = NULL;
  179.                     newarg->ai_type = 0;
  180.                     newarg->ai_flags = 0;
  181.                     newarg->ai_misc1.ai_lolim = 0;
  182.                     newarg->ai_misc2.ai_uplim = 0;
  183.                     newarg->ai_dest = NULL;
  184.                     newarg->ai_func = NULL;
  185.                     newarg->ai_help = NULL;
  186.  
  187.                     new_id = strtok(nxtdef, "/");
  188.  
  189.                     typestr = strtok(NULL, "/");
  190.  
  191.                     /*
  192.                      * get argument type
  193.                      */
  194.                     if (typestr)
  195.                     {
  196.  
  197.                         if (strlen(typestr) == 1)
  198.                         {
  199.  
  200.                             switch (toupper(typestr[0]))
  201.                             {
  202.  
  203.                             case 'T':
  204.                                 new_type = ARG_TEXT;
  205.                                 break;
  206.  
  207.                             case 'S':
  208.                                 new_type = ARG_SWITCH;
  209.                                 break;
  210.  
  211.                             case 'N':
  212.                                 new_type = ARG_LONG;
  213.                                 break;
  214.  
  215.                             case 'R':
  216.                                 new_type = ARG_LONG_RANGE;
  217.                                 break;
  218.  
  219.                             case 'E':
  220.                                 new_type = ARG_ENUM;
  221.                                 break;
  222.  
  223.                             }
  224.  
  225.                             if (new_type)       /* arg-type specified? */
  226.                                 flagstr =       /* Y-> get next flag */
  227.                                     strtok(NULL, "/");
  228.                             else
  229.                             {
  230.  
  231.                                 flagstr = typestr;      /* N-> must be flag */
  232.                                 new_type = ARG_TEXT;    /*     set type to text */
  233.  
  234.                             }
  235.  
  236.                         }
  237.                         else
  238.                             set_preperr(APE_INVALID_TEMPLATE, 0);
  239.  
  240.                     }
  241.                     else
  242.                     {           /* no type at all */
  243.  
  244.                         flagstr = NULL;         /* -> no flags also */
  245.                         new_type = ARG_TEXT;    /*    set type to text */
  246.  
  247.                     }           /* if typestr */
  248.  
  249.                     /*
  250.                      * get argument flags
  251.                      */
  252.                     while (flagstr && flagstr[0] && no_preperr)
  253.                     {
  254.  
  255.                         switch (toupper(flagstr[0]))
  256.                         {
  257.  
  258.                         case 'M':
  259.                             new_flags |= ARG_MULTIPLE;
  260.                             break;
  261.  
  262.                         case 'A':
  263.                             new_flags |= ARG_REQUIRED;
  264.                             break;
  265.  
  266.                         case 'K':
  267.                             new_flags |= ARG_KEYWORD;
  268.                             break;
  269.  
  270.                         case 'O':
  271.                             new_flags |= ARG_OVERWRITE;
  272.                             break;
  273.  
  274.                         case '$':
  275.                             new_flags |= ARG_HANDLEFUNC;
  276.                             break;
  277.  
  278.                         default:
  279.                             set_preperr(APE_ILLEGAL_FLAG, 0);
  280.                             break;
  281.  
  282.                         }       /* switch */
  283.  
  284.                         flagstr = strtok(NULL, "/");
  285.  
  286.                     }           /* while */
  287.  
  288.                     if (no_preperr)
  289.                     {
  290.  
  291.                         /*
  292.                          * get additional arguments
  293.                          */
  294.                         if (new_flags & ARG_HANDLEFUNC)
  295.                         {
  296.  
  297.                             /*
  298.                              * get handler function
  299.                              */
  300. #if 1
  301.                             APTR func_tmp = va_arg(ap, STRPTR);
  302.                             newarg->ai_func = (STRPTR(*)(STRPTR)) func_tmp;
  303. #else
  304.                             /* tricky type-cast, 1-step-version, does */
  305.                             /* not work with several compilers */
  306.                             newarg->ai_func = va_arg(ap, STRPTR(*)(STRPTR));
  307. #endif
  308.  
  309.                         }
  310.  
  311.                         if (new_type == ARG_LONG_RANGE)
  312.                         {
  313.  
  314.                             /*
  315.                              * get range limits
  316.                              */
  317.                             rnlolim = va_arg(ap, LONG);
  318.                             rnhilim = va_arg(ap, LONG);
  319.  
  320.                         }
  321.                         else if (new_type == ARG_ENUM)
  322.                         {
  323.  
  324.                             /*
  325.                              * get enum string
  326.                              */
  327.                             enumstr = va_arg(ap, STRPTR);
  328.  
  329.                         }
  330.  
  331.                         if (no_preperr)
  332.                         {
  333.  
  334.                             newarg->ai_id = strclone(new_id);   /* sux */
  335.                             newarg->ai_type = new_type;
  336.                             newarg->ai_flags = new_flags;
  337.                             newarg->ai_dest = va_arg(ap, APTR);
  338.                             newarg->ai_help =
  339.                                 strclone(va_arg(ap, STRPTR));
  340.  
  341.                             /*
  342.                              * set additional argument information
  343.                              * (->misc1, ->misc2)
  344.                              */
  345.                             switch (new_type)
  346.                             {
  347.  
  348.                             case ARG_ENUM:
  349.                                 newarg->ai_misc1.ai_enum = strclone(enumstr);
  350.                                 if (!(newarg->ai_misc1.ai_enum))
  351.                                     set_preperr(APE_NO_MEM, 0);
  352.                                 break;
  353.  
  354.                             case ARG_LONG_RANGE:
  355.                                 newarg->ai_misc1.ai_lolim = rnlolim;
  356.                                 newarg->ai_misc2.ai_uplim = rnhilim;
  357.                                 break;
  358.  
  359.                             }
  360.  
  361.                             /*
  362.                              * check for NULL as destination var
  363.                              */
  364.                             if (newarg->ai_dest == NULL)
  365.                                 set_preperr(APE_DESTVAR_IS_NULL, 0);
  366.  
  367.                         }
  368.  
  369.                         /*
  370.                          * check, if arg multiple arg without keyword
  371.                          */
  372.                         if (new_flags & ARG_MULTIPLE)
  373.                             if (!(new_flags & ARG_KEYWORD))
  374.                                 if (new_arglist->al_multiple)
  375.                                     set_preperr(APE_DOUBLE_MULTIPLE, 0);
  376.                                 else
  377.                                     new_arglist->al_multiple = newarg;
  378.  
  379.                         /*
  380.                          * append new argument entry to list
  381.                          */
  382.                         if (no_preperr)
  383.                             if (app_dlnode(newlist, (APTR) newarg)
  384.                                 == NULL)
  385.                                 set_preperr(APE_NO_MEM, 0);
  386.  
  387.                         /* free _newarg if any error occured */
  388.                         if (any_preperr)
  389.                             del_arginfo((APTR) newarg);
  390.  
  391.                     }
  392.  
  393.                 }
  394.                 else
  395.                     set_preperr(APE_NO_MEM, 0);
  396.  
  397.             }
  398.             else
  399.             {
  400.  
  401.                 DA(fprintf(stderr, DUA "  (end prepare)\n"));
  402.  
  403.             }
  404.  
  405.         }
  406.         while (nxtdef && no_preperr);
  407.  
  408.         /* free last value of nxtdef */
  409.         ufreestr(nxtdef);
  410.  
  411. #if 0
  412.         while (nxtdef)          /* flush arguments */
  413.             nxtdef = va_arg(ap, STRPTR);        /* (in error case) */
  414. #endif
  415.         va_end(ap);
  416.  
  417.     }
  418.     else
  419.         set_preperr(APE_NO_MEM, 0);
  420.  
  421.     /*
  422.      * check for empty template
  423.      */
  424.     if (no_preperr)
  425.         if (newlist->first == NULL)
  426.             set_preperr(APE_EMPTY_TEMPLATE, 0);
  427.  
  428.     /*
  429.      * free newlist, if any error occured
  430.      */
  431.     if (any_preperr)
  432.     {
  433.  
  434.         /* free newlist */
  435.         del_dllist(newlist);
  436.         ufree(new_arglist);
  437.         newlist = NULL;
  438.         new_arglist = NULL;
  439.  
  440.     }
  441.     else
  442.         new_arglist->al_list = newlist;
  443.  
  444.     return new_arglist;
  445.  
  446. }
  447.  
  448.